using System;

using NUnit.Framework;

using StructureMap.AutoMocking;
using StructureMap.TypeMockAutoMocker;

using TypeMock;

namespace StructureMap.TypeMockAutoMockerTesting
{
	public abstract class ClassiAutoMockerTesterBase<TCutWithAbstractMock, TCutWithConcreteMock>: AutoMockerTesterBase<TCutWithAbstractMock, TCutWithConcreteMock> where TCutWithAbstractMock: class, IConsumer where TCutWithConcreteMock: class, IConsumer
	{
		protected override MockMode MockMode
		{
			get { return MockMode.RecordAndReplay; }
		}

		[Test]
		public void CanUseRecorderSemanticsOnAbstractProviderForMocking()
		{
			var consumerAutoMocker = createAutoMockerWithAbstractMock();
			var provider = consumerAutoMocker.Get<IMock>();
			// Arrange
			using (var recorder = RecorderManager.StartRecording())
			{
				recorder.ExpectAndReturn(provider.Call(7), 8).CheckArguments();
			}
			// Act
			consumerAutoMocker.PartialMockTheClassUnderTest();
			consumerAutoMocker.ClassUnderTest.CallMock(7);
			// Assert
			MockManager.Verify();
		}

		[Test]
		public void CanUseRecorderSemanticsWithAbstractProviderForStubbing()
		{
			var consumerAutoMocker = createAutoMockerWithAbstractMock();
			var provider = consumerAutoMocker.Get<IMock>();
			// Arrange
			using (var recorder = RecorderManager.StartRecording())
			{
				recorder.ExpectAndReturn(provider.Call(7), 8).CheckArguments();
			}
			// Act
			consumerAutoMocker.PartialMockTheClassUnderTest();
			Assert.AreEqual(8, consumerAutoMocker.ClassUnderTest.CallMock(7), "the stub didn't return the expected value for a stub. Somehow the AutoMocker hasn't setup it correctly");
		}

		[Test]
		public void CanUseRecorderSemanticsWithConcreteProviderForMocking()
		{
			var consumerAutoMocker = createAutoMockerWithConcreteMock();
			var provider = consumerAutoMocker.Get<ConcreteProvider>();
			// Arrange
			using (var recorder = RecorderManager.StartRecording())
			{
				recorder.ExpectAndReturn(provider.Call(7), 8).CheckArguments();
			}
			// Act
			consumerAutoMocker.PartialMockTheClassUnderTest();
			consumerAutoMocker.ClassUnderTest.CallMock(7);
			// Assert
			MockManager.Verify();
		}

		[Test]
		public void CanUseRecorderSemanticsWithConcreteProviderForStubbing()
		{
			var consumerAutoMocker = createAutoMockerWithConcreteMock();
			var provider = consumerAutoMocker.Get<ConcreteProvider>();
			// Arrange
			using (var recorder = RecorderManager.StartRecording())
			{
				recorder.ExpectAndReturn(provider.Call(7), 8).CheckArguments();
			}
			// Act
			consumerAutoMocker.PartialMockTheClassUnderTest();
			Assert.AreEqual(8, consumerAutoMocker.ClassUnderTest.CallMock(7), "the stub didn't return the expected value for a stub. Somehow the AutoMocker hasn't setup it correctly");
		}
	}
}